﻿using System;
using System.Text;
using System.Reflection;
using System.Configuration;
using System.Globalization;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Resources;

namespace VirusCleaner.Language
{
    /*
 * 1、使用前在配置文件（App.config）里面添加配置节                                                
  <appSettings>
    <add key="default" value="LanguageRes\ChineseResource.resx"/>
    <add key="zh-CN" value="LanguageRes\ChineseResource.resx"/>
    <add key="en-US" value="LanguageRes\EngLishResource.resx"/>
    <add key="ja-JP" value="LanguageRes\JapaneseResource.resx"/>    
    注意：上面配置中value中的LanguageRes指该解决方案中多所有项目多字符串语言的配置的语言文件夹为LanguageRes。
  </appSettings>
  2、获得字符串语言包中多字符串方法
     例如语言资源包中有一个名称为“button”多字符串，获取方法如下
     string temp = LanguageString.GetString("button"); 
     
  3、更换语言方法
     第一步：指定当前线程语言： System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("ja-JP");
             其中字符串"ja-JP"指的是语言
     第二步：软件语言换为当前线程语言：
            LanguageString.SetLanguage(System.Threading.Thread.CurrentThread.CurrentUICulture);
            
     或许直接用LanguageString.SetLanguage(new System.Globalization.CultureInfo("ja-JP"));
 * 
 * */
    /// <summary>
    /// 多语言字符串
    /// </summary>
    public class LanguageString
    {
        #region 构造方法

        //语言资源管理器
        private static ResourceManager _resourceManager = null;
        //当前程序集名字
        private static string _currAssemblyName = string.Empty;
        //当前语言
        private static string _currLanguageName = "default";
        //当前资源包 
        private static string _currLanguagePack = null;
        //当前程序集
        private static Assembly _currAssembly = null;

        public static readonly string _lock_ = "_lock_";

        private static global::System.Globalization.CultureInfo _resourceCulture;

        private readonly static Regex Pattern = new Regex(@"\$\{[^\}]+\}", RegexOptions.Compiled | RegexOptions.CultureInvariant);

        private readonly static Regex PatternInner = new Regex(@"(?<=\${)([^\}]*)?(?=\})", RegexOptions.Compiled | RegexOptions.CultureInvariant);
        
        /// <summary>
        /// 构造方法
        /// </summary>
        public LanguageString()
        {
            //
        }
        #endregion
        #region 内部属性

        /// <summary>
        ///语言管理器 
        /// </summary>
        internal static System.Resources.ResourceManager ResourceManager
        {
            get
            {
                return _resourceManager;
            }
        }

        /// <summary>
        /// 当前程序集名字
        /// </summary>
        internal static string CurrentAssemblyName
        {
            get
            {
                return _currAssemblyName;
            }
        }



        /// <summary>
        ///   当前语言名称
        /// </summary>
        internal static string CurrentLanguageName
        {
            get
            {
                return _currLanguageName;
            }
            set
            {
                _currAssemblyName = value;
                SetLanguageName();
            }
        }

        internal System.Globalization.CultureInfo Culture
        {
            get
            {
                return _resourceCulture;
            }
            set
            {
                _resourceCulture = value;
            }
        }

        #endregion
        #region 外部属性


        #endregion
        #region 私有方法
        /// <summary>
        /// 设置语言名
        /// </summary>
        private static void SetLanguageName()
        {
            string currentName = System.Threading.Thread.CurrentThread.CurrentUICulture.Name;
            if (_currLanguageName != currentName)
            {
                _currLanguageName = currentName;

                SetResManager();
            }
        }

        /// <summary>
        /// 设置程序集
        /// </summary>
        /// <param name="aAssembly">Assembly</param>
        private static void SetAssembly(Assembly aAssembly)
        {
            if (_currAssemblyName != aAssembly.FullName)
            {
                _currAssembly = aAssembly;
                _currAssemblyName = aAssembly.FullName.Substring(0, aAssembly.FullName.IndexOf(','));

                SetResManager();
            }
        }


        /// <summary>
        /// 设置语言管理器
        /// </summary>
        private static void SetResManager()
        {
            SetResPath();
            if (_currLanguagePack != string.Empty && _currAssembly != null)
            {
                try
                {
                    _resourceManager = new System.Resources.ResourceManager(_currLanguagePack, _currAssembly)
                                           {IgnoreCase = true};
                }
                catch
                {
                    ;
                }
            }
        }

        /// <summary>
        /// 资源路径
        /// </summary>
        private static void SetResPath()
        {            
            if (String.IsNullOrEmpty(_currLanguageName))
            {
                _currLanguageName = System.Threading.Thread.CurrentThread.CurrentCulture.Name;
            }
            //优先读取配置文件指定的语言
            string resPath = @"LanguageRes\ChineseResource.resx";//ConfigurationManager.AppSettings[_currLanguageName];            

            if (resPath.IndexOf(".resx") > -1)
            {
                resPath = resPath.Replace(".resx", "").Replace('\\', '.').Replace('/', '.');
            }
            if (!String.IsNullOrEmpty(_currAssemblyName))
            {
                _currLanguagePack = String.Concat(_currAssemblyName, ".", resPath);
            }
        }

        /// <summary>
        /// 控件申请资源 改变控件的语言
        /// </summary>
        /// <param name="aParentControl">父控件</param>
        /// <param name="aRes">资源管理器</param>
        private static void ChangeControlsLanguage(Control aParentControl, System.ComponentModel.ComponentResourceManager aRes)
        {
            foreach (Control control in aParentControl.Controls)
            {
                aRes.ApplyResources(control, control.Name);
                if (control.Controls.Count > 0)
                {
                    ChangeControlsLanguage(control, aRes);
                }
            }
        }

        #endregion
        #region 公有方法
        /// <summary>
        /// 表达式获取当前语言对应的字符串
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string Parse(string input)
        {
            if (input == null)
                return String.Empty;

            string result = input;
            string resString;
            MatchCollection matchs = Pattern.Matches(input);
            foreach (Match match in matchs)
            {
                resString = LanguageString.GetString(PatternInner.Match(match.Value).Value);
                if (resString != null)
                {
                    resString = resString.Replace("$NewLine$", System.Environment.NewLine);
                    result = result.Replace(match.Value, resString);
                }
                else
                {
                    result = result.Replace(match.Value, "/");
                }
            }

            return result;
        }

        /// <summary>
        /// 应用所有资源
        /// </summary>
        /// <param name="userControl"></param>
        public static void ApplyResource(UserControl userControl)
        {
            userControl.Text = Parse(userControl.Text);

            foreach (Control control in userControl.Controls)
            {
                ApplyResource(control);
            }
        }

        public static void ApplyResource(Form form)
        {
            form.Text = Parse(form.Text);

            foreach (Control control in form.Controls)
            {
                ApplyResource(control);
            }
        }

        public static void ApplyResource(Control control)
        {
            control.Text = Parse(control.Text);
            foreach (Control ctrl in control.Controls)
            {
                ApplyResource(ctrl);
            }

            if (control.ContextMenuStrip != null)
            {
                ContextMenuStrip contextMenuStrip = control.ContextMenuStrip as ContextMenuStrip;
                ApplyResource(contextMenuStrip);
            }

            if (control is DataGridView)
            {
                DataGridView dataGridView = control as DataGridView;
                ApplyResource(dataGridView);
            }

            if (control is ToolStrip)
            {
                ToolStrip toolStrip = control as ToolStrip;
                ApplyResource(toolStrip);
            }
        }

        public static void ApplyResource(DataGridView dataGridView)
        {
            foreach (DataGridViewColumn column in dataGridView.Columns)
            {
                column.HeaderText = Parse(column.HeaderText);
            }
        }

        public static void ApplyResource(ToolStrip toolStrip)
        {
            foreach (System.Windows.Forms.ToolStripItem item in toolStrip.Items)
            {
                item.Text = Parse(item.Text);
                if (item is ToolStripDropDownItem)
                {
                    ToolStripDropDownItem toolStripDropDownItem = item as ToolStripDropDownItem;
                    ApplyResource(toolStripDropDownItem.DropDownItems);
                }
            }
        }

        public static void ApplyResource(ContextMenuStrip contextMenuStrip)
        {
            ApplyResource(contextMenuStrip.Items);
        }

        public static void ApplyResource(ToolStripItemCollection items)
        {
            foreach (System.Windows.Forms.ToolStripItem item in items)
            {
                item.Text = Parse(item.Text);
                if (item is ToolStripMenuItem)
                {
                    ToolStripMenuItem toolStripMenuItem = item as ToolStripMenuItem;
                    ApplyResource(toolStripMenuItem.DropDownItems);
                }
            }
        }
        /// <summary>
        /// 更新所有界面
        /// </summary>
        public static void ApplyResource()
        {
            foreach (System.Windows.Forms.Form form in Application.OpenForms)
            {
                var res = new System.ComponentModel.ComponentResourceManager(form.GetType());
                res.ApplyResources(form, "$this");
                ChangeControlsLanguage(form, res);
            }
        }
        /// <summary>
        /// 根据字符串名字获得，当前语言对应字符串
        /// </summary>
        /// <param name="aStrName">查询的字符串</param>
        /// <returns>语言对应的字符串</returns>
        public static string GetString(string aStrName)
        {
            lock (_lock_)
            {
                SetAssembly(Assembly.GetCallingAssembly());
                try
                {
                    return ResourceManager.GetString(aStrName, _resourceCulture);
                }
                catch
                {
                    return string.Empty;
                }
            }
        }
        /// <summary>
        /// 当前资源集中获取字符串
        /// </summary>
        /// <param name="aStrName">查询的字符串</param>
        /// <returns>语言对应的字符串</returns>
        public static string GetStringA(string aStrName)
        {
            return GetString(aStrName);
        }
        /// <summary>
        /// 设置语言
        /// </summary>
        public static void SetLanguage(CultureInfo culture)
        {
            if (_currLanguageName != culture.Name)
            {
// ReSharper disable RedundantCheckBeforeAssignment
                if (System.Threading.Thread.CurrentThread.CurrentUICulture != culture)
// ReSharper restore RedundantCheckBeforeAssignment
                {
                    System.Threading.Thread.CurrentThread.CurrentUICulture = culture;
                }
                _currLanguageName = culture.Name;
                SetResManager();
                ApplyResource();
            }
        }
        public static void SetLanguage(string lang)
        {
            System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(lang);
            SetLanguage(System.Threading.Thread.CurrentThread.CurrentUICulture);
        }
        #endregion
    }
}